package com.ruoyi.common.utils;

import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.ParseException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.util.Date;

@UtilityClass
public class LocalDateTimeUtil {
    private final String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM",
            "yyyy年MM月dd日"};

    /**
     * 日期型字符串转化为日期 格式
     */
    public static LocalDateTime parseDateTime(Object str) {
        if (str == null) {
            return null;
        }
        if (str instanceof Date) {
            return parseDateTime((Date) str);
        }
        try {
            return parseDateTime(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    public LocalDateTime parseDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    public String parseStr(final String format, final Object date) {
        if (date instanceof Date) {
            return DateFormatUtils.format((Date) date, format);
        } else if (date instanceof LocalDateTime) {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
            return dateTimeFormatter.format((LocalDateTime) date);
        } else if (date instanceof LocalDate) {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
            return dateTimeFormatter.format((LocalDate) date);
        }
        return "";
    }

    public String parseStr(final Object date) {
        if (date instanceof Date) {
            return DateFormatUtils.format((Date) date, parsePatterns[1]);
        } else if (date instanceof LocalDateTime) {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(parsePatterns[1]);
            return dateTimeFormatter.format((LocalDateTime) date);
        } else if (date instanceof LocalDate) {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(parsePatterns[0]);
            return dateTimeFormatter.format((LocalDate) date);
        }
        return "";
    }


    public LocalDate parseDate(Object str) {
        if (str == null) {
            return null;
        }
        if (str instanceof Date) {
            return parseDate((Date) str);
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    public LocalDate parseDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        return LocalDate.ofInstant(instant, zone);
    }

    public LocalDateTime parseDateTimeOfTimestamp(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    public LocalDate parseDateOfTimestamp(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        ZoneId zone = ZoneId.systemDefault();
        return LocalDate.ofInstant(instant, zone);
    }


    private LocalDate parseDate(String str, String... parsePatterns) throws ParseException {
        if (str != null && parsePatterns != null) {
            for (String parsePattern : parsePatterns) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(parsePattern);
                try {
                    if (parsePattern.length() == str.length()) {
                        return LocalDate.parse(str, formatter);
                    }
                } catch (Exception e) {

                }
            }
            throw new ParseException("Unable to parse the date: " + str, -1);
        } else {
            throw new IllegalArgumentException("Date and Patterns must not be null");
        }
    }

    private LocalDateTime parseDateTime(String str, String... parsePatterns) throws ParseException {
        if (str != null && parsePatterns != null) {
            for (String parsePattern : parsePatterns) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(parsePattern);
                try {
                    if (parsePattern.length() == str.length()) {
                        return LocalDateTime.parse(str, formatter);
                    }
                } catch (Exception e) {

                }
            }
            throw new ParseException("Unable to parse the date: " + str, -1);
        } else {
            throw new IllegalArgumentException("Date and Patterns must not be null");
        }
    }


    public String getDurationBetween(Temporal startInclusive, Temporal endExclusive) {
        Duration between = Duration.between(startInclusive, endExclusive).abs();
        long minutes = between.toMinutes();
        if (minutes == 0) {
            return "1分钟";
        }
        if (minutes < 60) {
            return minutes + "分钟";
        }
        long hours = between.toHours();
        if (hours < 24) {
            long m = minutes - hours * 60;
            return hours + "小时" + m + "分";
        }
        long days = between.toDays();
        long h = hours - days * 24;
        return days + "天" + h + "小时";
    }
}
